package main

import (
	"crypto/rand"
	"device/util"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/emmansun/gmsm/sm2"
	"github.com/llightos/efind"
	"log"
	mrand "math/rand"
	"time"

	"github.com/emmansun/gmsm/sm3"
)

var (
	path        = "./"
	privateFile = "private.pem" //私钥文件
	publicFile  = "public.pem"  //公钥文件
	data        = "hello 国密"
	etcdAddr    = "192.168.146.1:2379"
)

// SPAPacket SPA数据包结构体
type SPAPacket struct {
	ID              int    `json:"id"`
	Token           string `json:"token"`
	RandomValue     int64  `json:"randomValue"`
	Username        string `json:"username"`
	Timestamp       string `json:"timestamp"`
	FKOVersion      string `json:"FKOVersion"`
	MessageType     string `json:"messageType"`
	NatAccess       string `json:"natAccess"`
	Auth            string `json:"auth"`
	ClientTimeOut   int    `json:"clientTimeOut"`
	EncryptionType  string `json:"encryptionType"`
	DigestType      string `json:"digestType"`
	SignatureType   string `json:"signatureType"`
	Protocol        string `json:"protocol"`
	SourcePort      int    `json:"sourcePort"`
	DestinationPort int    `json:"destinationPort"`
	SourceIP        string `json:"sourceIP"`
	DestinationIP   string `json:"destinationIP"`
	SPAPacketBytes  int    `json:"SPAPacketBytes"`
}

// SM2SignVO SM2签名结构体 pem格式读取
type SM2SignVO struct {
	Sm2signForSoft string `json:"sm2_signForSoft"`
	Sm2signForHard string `json:"sm2_signForHard"`
}

// GenSPAHashMap 生成SPA哈希映射
func GenSPAHashMap(spaPacket *SPAPacket) map[string]string {
	SPAHashMap := make(map[string]string)

	// 第一步：生成SPA数据包
	fmt.Println("第一步：生成SPA数据包")
	//spaPacket := SPAPacket{}
	mrand.Seed(time.Now().UnixNano())
	randomValue := mrand.Int63n(1000000000) + 1
	spaPacket.RandomValue = randomValue
	spaPacket.Username = "彭开明"
	spaPacket.Timestamp = time.Now().Format("20060102150405.000")
	spaPacket.ID = int(DeviceCer().ID)
	spaPacket.Token = DeviceCer().Token
	spaPacket.FKOVersion = "3.0.0"
	spaPacket.MessageType = "Access message"
	spaPacket.NatAccess = "NO"
	spaPacket.Auth = "YES"
	spaPacket.ClientTimeOut = 0
	spaPacket.EncryptionType = "SM4"
	spaPacket.DigestType = "SM3"
	spaPacket.SignatureType = "SM2"
	spaPacket.Protocol = "UDP"
	spaPacket.SourcePort = 65652
	spaPacket.DestinationPort = 22
	spaPacket.SourceIP = "192.168.146.10"
	spaPacket.DestinationIP = "192.168.146.11"
	spaPacket.SPAPacketBytes = 225

	fmt.Println(spaPacket)
	fmt.Println()

	// 第二步对SPA数据包进行加密
	fmt.Println("第二步对SPA数据包进行加密，先将spaPacket对象转为JSON字符串")
	jsonBytes, err := json.Marshal(spaPacket)
	if err != nil {
		fmt.Println("Error marshalling JSON:", err)
		return SPAHashMap
	}
	jsonString := string(jsonBytes)
	fmt.Println("将spaPacket对象转成json:")
	fmt.Println(jsonString)
	SPAHashMap["SPAJson"] = jsonString
	key := "1234567890ABCDEF1234567890ABCDEF"

	fmt.Println("CBC模式加密")
	cbc := util.Sm4EncryptCBC(jsonString, key)
	fmt.Println("密文: " + cbc)
	SPAHashMap["密文"] = cbc

	mingwen := util.Sm4DecryptCBC(cbc, key)
	fmt.Println("明文________________________", mingwen)

	// 第三步计算spaPacket的消息摘要
	fmt.Println("第三步计算spaPacket的消息摘要")
	sm3 := sm3.New()
	sm3.Write(jsonBytes)
	md := sm3.Sum(nil)
	sm3MAC := hex.EncodeToString(md)
	fmt.Println("单包信息的摘要结果为：" + sm3MAC)
	fmt.Println()
	SPAHashMap["摘要"] = sm3MAC

	//第四步客户端对单包信息进行签名
	fmt.Println("第四步客户端对单包信息进行签名")
	fmt.Println("--产生SM2秘钥--:")
	generateKey, _ := util.ReadKeyFromFile()

	fmt.Println("签名测试开始:")
	PrivateKey, err := sm2.NewPrivateKey(generateKey.D.Bytes())
	if err != nil {
		panic(err)
	}
	sign, err := PrivateKey.Sign(rand.Reader, jsonBytes, sm2.DefaultSM2SignerOpts)
	if err != nil {
		panic(err)
	}
	fmt.Println("签名信息：", hex.EncodeToString(sign))

	SPAHashMap["签名"] = hex.EncodeToString(sign)

	return SPAHashMap
}

func NewSPAPackage() *SPAPacket {
	spaPacket := new(SPAPacket)
	randomValue := mrand.Int63n(1000000000) + 1
	spaPacket.RandomValue = randomValue
	spaPacket.Username = "彭开明"
	spaPacket.Timestamp = time.Now().Format("20060102150405.000")
	spaPacket.ID = 2
	spaPacket.Token = "RLWbhQiLFQeJRgbyxCFI"
	spaPacket.FKOVersion = "3.0.0"
	spaPacket.MessageType = "Access message"
	spaPacket.NatAccess = "NO"
	spaPacket.Auth = "YES"
	spaPacket.ClientTimeOut = 0
	spaPacket.EncryptionType = "SM4"
	spaPacket.DigestType = "SM3"
	spaPacket.SignatureType = "SM2"
	spaPacket.Protocol = "UDP"
	spaPacket.SourcePort = 65652
	spaPacket.DestinationPort = 22
	spaPacket.SourceIP = "192.168.146.10"
	spaPacket.DestinationIP = "192.168.146.11"
	spaPacket.SPAPacketBytes = 225

	return spaPacket
}

// GetGatawayIP 需要获取服务时随时调用此方法
func GetGatawayIP() string {
	client := efind.NewClient(efind.Config{
		EtcdAddr: etcdAddr,
		TTL:      5,
	})
	server, err := client.MatchAServer("/etcd/gataway")
	if err != nil {
		log.Println(err)
		return "err"
	}
	return server.Val
}

func GetKeyCenterIP() string {
	client := efind.NewClient(efind.Config{
		EtcdAddr: etcdAddr,
		TTL:      5,
	})
	server, err := client.MatchAServer("/etcd/keycenter")
	if err != nil {
		log.Println(err)
		return "err"
	}
	return server.Val
}

// 生成SM2签名
//func (packet *SPAPacket) sm2(path string) {
//	GerenateSM2Key()
//}

func getSm2SignForSoft() {

}

func getSm2SignForHard() {

}

//func GenerateSM2Key() {
//	//1. 秘钥产生
//	priKey, err := sm2.GenerateKey(rand.Reader)
//	if err != nil {
//		fmt.Println("秘钥产生失败：", err)
//		os.Exit(1)
//	}
//	pubKey := &priKey.PublicKey
//	//生成文件 保存私钥
//	//x509编码
//	pemPrivKey, err := x509.WritePrivateKeyToPem(priKey, nil)
//	privateFile, err := os.Create(path + privateFile)
//	defer privateFile.Close()
//	privateFile.Write(pemPrivKey)
//
//	pemPublicKey, err := x509.WritePublicKeyToPem(pubKey)
//	publicFile, err := os.Create(path + publicFile)
//	defer publicFile.Close()
//	publicFile.Write(pemPublicKey)
//
//}

//func main() {
//	fmt.Println("开始生成SPA哈希映射:")
//	SPAHashMap := GenSPAHashMap()
//	fmt.Println("生成的SPA哈希映射:")
//	fmt.Println(SPAHashMap)
//
//	//Sm4Sample()
//}
